﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Schema;
using System.Reflection;

namespace DP.Sharepoint.SiteWorkflow.SSIS
{
    /// <summary>
    /// 
    /// </summary>
    public class WorkflowParameterMappingManger
    {
        bool _schemaAdded;

        XmlDocument _mappingDoc;
        /// <summary>
        /// provides methods for working with SharepointSiteWorkflowDestination's intenal column mapping micro format
        /// </summary>
        /// <param name="mappingData"></param>
        public WorkflowParameterMappingManger(string mappingData)
        {

            _mappingDoc = new XmlDocument();
            _mappingDoc.LoadXml(mappingData);

            ValidateMappingData();


        }

        /// <summary>
        ///  provides methods for working with SharepointSiteWorkflowDestination's intenal column mapping micro format
        /// </summary>
        public WorkflowParameterMappingManger()
        {
            _mappingDoc = new XmlDocument();
            _mappingDoc.LoadXml("<WorkflowParameterMappings></WorkflowParameterMappings>");

        }

        /// <summary>
        /// adds mapping to the mapping collection
        /// </summary>
        /// <param name="mappedToColumnName"></param>
        /// <param name="workflowParameterName"></param>
        /// <returns>true is success</returns>
        public bool AddMapping(string mappedToColumnName, string workflowParameterName)
        {
            if (string.IsNullOrEmpty(mappedToColumnName) || string.IsNullOrEmpty(workflowParameterName))
                return false;

            if (MappingExists(mappedToColumnName))
                return false;

            var mappingNode = _mappingDoc.CreateNode(XmlNodeType.Element, "WorkflowParameterMapping", null);

            var paramNode = _mappingDoc.CreateNode(XmlNodeType.Element, "ParameterName", null);

            paramNode.InnerText = workflowParameterName;

            var mappedToNode = _mappingDoc.CreateNode(XmlNodeType.Element, "MappedToColumnName", null);

            mappedToNode.InnerText = mappedToColumnName;

            mappingNode.AppendChild(paramNode);

            mappingNode.AppendChild(mappedToNode);

            _mappingDoc.DocumentElement.AppendChild(mappingNode);


            return true;
        }

        /// <summary>
        /// removes a mapping 
        /// </summary>
        /// <param name="mappedToColumnName"></param>
        /// <returns></returns>
        public bool RemoveMapping(string mappedToColumnName)
        {
            if (!MappingExists(mappedToColumnName))
                return false;

            var node = _mappingDoc.SelectSingleNode("/WorkflowParameterMappings/WorkflowParameterMapping[MappedToColumnName='" + mappedToColumnName + "']");

            node.ParentNode.RemoveChild(node);

            return true;


        }
        /// <summary>
        /// checks if the mapping exists
        /// </summary>
        /// <param name="mappedToColumnName"></param>
        /// <returns></returns>
        public bool MappingExists(string mappedToColumnName)
        {
            return _mappingDoc.SelectSingleNode("/WorkflowParameterMappings/WorkflowParameterMapping[MappedToColumnName='" + mappedToColumnName + "']") != null;

        }

        private void ValidateMappingData()
        {
            using (StreamReader mySchemaReader = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("DP.Sharepoint.SiteWorkflow.SSIS.WorkflowParameterMapping.xsd")))
            {

                string schema = mySchemaReader.ReadToEnd();

                XmlTextReader myXmlReader = new XmlTextReader(new System.IO.StringReader(schema));

                if (!_schemaAdded)
                {
                    _mappingDoc.Schemas.Add(null, myXmlReader);
                    _schemaAdded = true;
                }

                _mappingDoc.Validate(null);
            }
        }

        /// <summary>
        /// returns mapping collecting in XML format
        /// </summary>
        /// <returns></returns>
        public string GetMappingsAsString()
        {
            ValidateMappingData();

            StringBuilder sb = new StringBuilder();

            using (StringWriter sw = new StringWriter(sb))
            {
                _mappingDoc.Save(sw);

                return sb.ToString();
            }
        }

        /// <summary>
        /// returns mapping data for foreach statements
        /// </summary>
        /// <returns></returns>
        public IEnumerable<KeyValuePair<string, string>> GetMappings()
        {
            foreach (XmlNode node in _mappingDoc.SelectNodes("/WorkflowParameterMappings/WorkflowParameterMapping"))
            {
                var kvp = new KeyValuePair<string, string>(node["MappedToColumnName"].InnerText, node["ParameterName"].InnerText);

                yield return kvp;

            }
        }

        /// <summary>
        /// returns mapping data for situations where key based lookups are needed
        /// </summary>
        /// <returns></returns>
        public IDictionary<string, string> GetMappingsDictionary()
        {
            Dictionary<string, string> res = new Dictionary<string, string>();

            foreach (var item in GetMappings())
            {

                res.Add(item.Key, item.Value);

            }

            return res;

        }

    }
}
